﻿using NoteManger;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using System.Web.Routing;
using WebCache;

namespace WorkWriter.Controllers
{
    public class NoteController : BaseController
    {
        private const string SQL_QUERY_YEAR_ALL_NOTE = @"SELECT NoteID,EmpID,NoteTopic,NoteBody,NoteDate,WorkLoad,NoteState,CreateDate,CreateTime,NoteMemo,Auditor,AuditDate,AuditTime,AuditWorkLoad,BeginTime,EndTime,TaskID,Address,Hospital
FROM   WorkNotes (NOLOCK)
WHERE  RecordState=0 AND EmpID = '{0}' AND NoteState IN (0, 1, 2) AND NoteDate LIKE '{1}-%'
ORDER  BY NoteDate ";

        private const string SQL_QUERY_NOTE_INFO = @"SELECT  NoteID,EmpID,NoteTopic,NoteBody,NoteDate,
	WorkLoad,NoteState,CreateDate,CreateTime,Auditor,
	AuditDate,AuditTime,AuditWorkLoad,BeginTime,EndTime,
	RecordState,NoteMemo,TaskID,Address,Hospital 
FROM WorkNotes (NOLOCK) WHERE EmpID = '{0}' AND NoteID = '{1}'";

        public ActionResult Index()
        {
            return View();
        }

        private Tuple<string, string>[] GetNoteCategories()
        {
            var categories = CacheProviders.GlobalCache[Keys.DICT_NOTE_CATEGORIES];
            if (categories == null)
            {
                string[,] arrResults = new string[0, 0];
                string message = string.Empty;
                bool flag = noteContext.CommonQuery(string.Format("select a.TaskID,a.TaskDesc,isnull(b.EmpType,0) from TaskType a(nolock),Employees b(nolock) where a.EmpType = isnull(b.EmpType,0) and b.EmpID = '{0}'", SysContext.User.LoginID), ref arrResults, ref message);
                if (!flag || arrResults == null) throw new Exception(message);
                int bound = arrResults.GetUpperBound(0) - arrResults.GetLowerBound(0) + 1;
                Tuple<string, string>[] arrCategories = new Tuple<string, string>[bound];
                for (int i = 0; i < bound; i++) arrCategories[i] = new Tuple<string, string>(arrResults[i, 0], arrResults[i, 1]);
                CacheProviders.GlobalCache.Add(Keys.DICT_NOTE_CATEGORIES, arrCategories, () => { CacheProviders.GlobalCache[Keys.DICT_NOTE_CATEGORIES] = null; return GetNoteCategories(); });
                return arrCategories;
            }
            return (Tuple<string, string>[])categories;
        }

        private List<Tuple<string, string, string>> GetAllAddress()
        {
            return (CacheProviders.GlobalCache[Keys.DICT_ADDRESS] as List<Tuple<string, string, string>>) ?? new List<Tuple<string, string, string>>();
        }
        [HttpGet]
        public ActionResult Edit()
        {
            ViewData["NoteCategories"] = this.GetNoteCategories();
            ViewData["Provinces"] = this.GetAllAddress().Where(c => c.Item3 == "0").ToArray();
            ViewData["Citys"] = new string[0];
            ViewBag.TASK_TYPE_WORKSITE = TWorkNoteItem.TASK_TYPE_WORKSITE;
            string sid = Convert.ToString(RouteData.Values["id"]);//Request["id"];
            decimal note_id = 0;
            string dformat = "yyyy-MM-dd";
            if (decimal.TryParse(sid, out note_id) && note_id > 0)
            {
                var arrResult = new string[0, 0];
                var message = string.Empty;
                var result = noteContext.CommonQuery(string.Format(SQL_QUERY_NOTE_INFO, SysContext.User.LoginID, note_id), ref arrResult, ref message);
                TWorkNoteItem item = new TWorkNoteItem();
                item.NoteID = note_id.ToString();
                item.NoteTopic = arrResult[0, 2];
                item.NoteBody = arrResult[0, 3];
                item.NoteDate = arrResult[0, 4];
                item.WorkLoad = arrResult[0, 5];
                item.NoteState = arrResult[0, 6];
                item.CreateDate = arrResult[0, 7];
                item.CreateTime = arrResult[0, 8];
                item.Auditor = arrResult[0, 9];
                item.AuditDate = arrResult[0, 10];
                item.AuditTime = arrResult[0, 11];
                item.AuditWorkLoad = arrResult[0, 12];
                item.BeginTime = arrResult[0, 13];
                item.EndTime = arrResult[0, 14];
                item.NoteMemo = arrResult[0, 16];
                item.TaskID = arrResult[0, 17];
                string address = arrResult[0, 18];
                item.Hospital = arrResult[0, 19];
                if (!string.IsNullOrWhiteSpace(address))
                {
                    var arr = address.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                    item.Province = arr.Length > 0 ? arr[0] : string.Empty;
                    item.City = arr.Length > 1 ? arr[1] : string.Empty;
                }
                DateTime noteDate;
                ViewBag.PrevDay = DateTime.TryParseExact(item.NoteDate, dformat, null, DateTimeStyles.None, out noteDate) ? noteDate.AddDays(-1).ToString(dformat) : DateTime.Now.AddDays(-1).ToString(dformat);
                ViewBag.NextDay = DateTime.TryParseExact(item.NoteDate, dformat, null, DateTimeStyles.None, out noteDate) ? noteDate.AddDays(1).ToString(dformat) : DateTime.Now.AddDays(1).ToString(dformat);
                return View(item);
            }
            DateTime editDate = DateTime.Now;
            if (!string.IsNullOrWhiteSpace(Request["ed"]) && !DateTime.TryParseExact(Request["ed"], dformat, null, DateTimeStyles.None, out editDate)) editDate = DateTime.Now;
            ViewBag.EditDay = editDate.ToString(dformat);
            ViewBag.PrevDay = editDate.AddDays(-1).ToString(dformat);
            ViewBag.NextDay = editDate.AddDays(1).ToString(dformat);
            return View();
        }

        public ActionResult ProvinceCitys()
        {
            string provinceCode = Request["provinceCode"];
            var arrAddress = this.GetAllAddress();
            var citys = arrAddress.Where(ad => ad.Item3 == provinceCode).ToArray();
            if (citys == null || citys.Length == 0) return Json(true);
            return Json(true, citys.Select(c => c.Item2).ToArray());
        }
        [HttpPost]
        public ActionResult Save(TWorkNoteItem item)
        {
            if (!string.IsNullOrEmpty(item.TaskID)) item.TaskID = item.TaskID.Split('_')[0];
            if (item.TaskID == TWorkNoteItem.TASK_TYPE_WORKSITE && !string.IsNullOrEmpty(item.Province)) item.Province = item.Province.Split('_')[1];
            if (item.NoteID == null) item.NoteID = string.Empty;
            string message = string.Empty;
            if (!noteContext.EditNote(SysContext.User.LoginID, item.NoteTopic, item.NoteBody, item.NoteDate, item.WorkLoad, item.BeginTime, item.EndTime, item.NoteID, !(item.NoteID.Length > 0), item.TaskID, item.Location, item.TaskID == TWorkNoteItem.TASK_TYPE_WORKSITE ? "-2" : "0", ref message)) throw new Exception(message);
            var date = item.NoteDate.Substring(0, 7);
            var allNotes = CacheProviders.SessionCache[Keys.WORKLOG_CACHE_KEY] as Dictionary<string, List<TWorkNoteItem>>;
            if (allNotes != null && allNotes.ContainsKey(date)) allNotes.Remove(date);
            return RedirectToAction("Edit", new { ed = item.NoteDate });
        }
        public ActionResult MonthNotes()
        {
            var month = Request["month"];
            if (month == null) throw new Exception("不正确的请求，未传入日期。");
            else if (month.Length == 7 && !Regex.IsMatch(month, @"[0-9][0-9][0-9][0-9]\-([0][0-9]|[1][0-2])")) throw new Exception("请求的月份格式不正确。");
            else if (month.Length == 10 && !Regex.IsMatch(month, @"[0-9][0-9][0-9][0-9]\-([0][0-9]|[1][0-2])\-[0-3][0-9]")) throw new Exception("请求的日期格式不正确。");
            else if (month.Length != 7 && month.Length != 10) throw new Exception("不正确的请求，传入日期不正确。");
            var user = SysContext.User;
            if (CacheProviders.SessionCache[Keys.WORKLOG_CACHE_KEY] == null)
            {
                var dictCaches = new Dictionary<string, List<TWorkNoteItem>>();
                CacheProviders.SessionCache[Keys.WORKLOG_CACHE_KEY] = dictCaches;
                dictCaches[month] = GetMonthNotes(user.LoginID, month);
                return Json(true, dictCaches[month].Select(n => new { NoteDate = n.NoteDate, Description = n.DayDescription }).Distinct());
            }
            else
            {
                var allNotes = CacheProviders.SessionCache[Keys.WORKLOG_CACHE_KEY] as Dictionary<string, List<TWorkNoteItem>>;
                if (allNotes.ContainsKey(month)) return Json(true, allNotes[month].Select(n => new { NoteDate = n.NoteDate, Description = n.DayDescription }).Distinct());
                else if (allNotes.ContainsKey(month.Substring(0, 7))) return Json(true, allNotes[month.Substring(0, 7)].FindAll(n => n.NoteDay == month.Substring(8, 2)));
                else if (month.Length == 7) allNotes[month] = GetMonthNotes(user.LoginID, month);

                return Json(true, allNotes[month].Select(n => new { NoteDate = n.NoteDate, Description = n.DayDescription }).Distinct());
            }

        }

        public ActionResult Contact()
        {
            var holiday = Holiday.Get(DateTime.Now.Year);
            ViewBag.UserName = SysContext.User.LoginName;
            ViewBag.WorkDays = holiday.WorkDays;
            ViewBag.WorkTimes = ViewBag.WorkDays * 8;

            var allNotes = this.GetAllNotes(SysContext.User.LoginID, DateTime.Now.Year);

            int d = allNotes.Where(n => n.TaskID == TWorkNoteItem.TASK_TYPE_WORKSITE).Select(n => n.NoteDate).Distinct().Count();
            ViewBag.WorksiteDays = d > 0 ? d.ToString() : "---";

            Func<string, DateTime> dateParse = s => {
                var arr = s.Split('-');
                return new DateTime(int.Parse(arr[0]), int.Parse(arr[1]), int.Parse(arr[2]));
            };
            d = allNotes.Where(n => !holiday.IsWorkDay(dateParse(n.NoteDate))).Select(n => n.NoteDate).Distinct().Count();
            ViewBag.OvertimeDays = d > 0 ? d.ToString() : "---";

            d = allNotes.Where(n => n.TaskID == TWorkNoteItem.TASK_TYPE_DAYOFF).Select(n => n.NoteDate).Distinct().Count();
            ViewBag.DaysOff = d > 0 ? d.ToString() : "---";

            d = allNotes.Where(n => n.TaskID == TWorkNoteItem.TASK_TYPE_LEAVE).Select(n => n.NoteDate).Distinct().Count();
            ViewBag.LeaveDays = d > 0 ? d.ToString() : "---";

            d = allNotes.Where(n => n.TaskID != TWorkNoteItem.TASK_TYPE_DAYOFF && n.TaskID != TWorkNoteItem.TASK_TYPE_LEAVE).Select(n => n.NoteDate).Distinct().Count();
            ViewBag.LackOf = holiday.GetWorkDays(DateTime.Today) - d;

            ViewBag.DoWorkDays = holiday.GetWorkDays(DateTime.Today) - int.Parse(ViewBag.DaysOff.Replace("-", "0")) - int.Parse(ViewBag.LeaveDays.Replace("-", "0"));

            ViewBag.SumWorkTimes = (8 * ViewBag.DoWorkDays) + allNotes.GroupBy(n => n.NoteDate).ToList().Sum(g => {
                var sum = g.ToList().Sum(it => decimal.Parse(it.WorkLoad));
                if (sum > 8) return sum - 8;
                return 0;
            });

            return View();
        }


        private List<TWorkNoteItem> GetAllNotes(string id, int year)
        {
            var allNotes = new List<TWorkNoteItem>();
            string[,] arrNotes = new string[0, 0];
            string message = string.Empty;
            var success = noteContext.CommonQuery(string.Format(SQL_QUERY_YEAR_ALL_NOTE, id, year), ref arrNotes, ref message);//GetDetailNoteList(id, string.Empty, year.ToString(), ref arrNotes, ref message);
            if (!success) throw new Exception(message);
            if (arrNotes == null) return new List<TWorkNoteItem>();

            int bound = arrNotes.GetUpperBound(0) - arrNotes.GetLowerBound(0) + 1;
            for (int i = 0; i < bound; i++)
            {
                int index = 0;
                if (string.IsNullOrWhiteSpace(arrNotes[i, index]) || arrNotes[i, index].Trim() == "0" || arrNotes[i, index].StartsWith("-")) continue;
                var item = new TWorkNoteItem();
                item.NoteID = arrNotes[i, index++];
                item.UserID = arrNotes[i, index++];
                item.NoteTopic = arrNotes[i, index++];
                item.NoteBody = arrNotes[i, index++];
                item.NoteDate = arrNotes[i, index++];
                item.WorkLoad = arrNotes[i, index++];
                item.NoteState = arrNotes[i, index++];
                item.CreateDate = arrNotes[i, index++];
                item.CreateTime = arrNotes[i, index++];
                item.NoteMemo = arrNotes[i, index++];
                item.Auditor = arrNotes[i, index++];
                item.AuditDate = arrNotes[i, index++];
                item.AuditTime = arrNotes[i, index++];
                item.AuditWorkLoad = arrNotes[i, index++];
                item.BeginTime = arrNotes[i, index++];
                item.EndTime = arrNotes[i, index++];
                item.TaskID = arrNotes[i, index++];

                item.NoteDate = item.NoteDate.Substring(item.NoteDate.IndexOf(year.ToString()), 10);
                item.NoteDay = item.NoteDate.Substring(item.NoteDate.Length - 2);
                decimal num = 0;
                item.WorkLoad = decimal.TryParse(item.WorkLoad, out num) ? num.ToString() : "0";
                allNotes.Add(item);

                var dictCaches = CacheProviders.SessionCache[Keys.WORKLOG_CACHE_KEY] as Dictionary<string, List<TWorkNoteItem>>;
                string month = item.NoteDate.Substring(0, 7);
                if (dictCaches == null) CacheProviders.SessionCache[Keys.WORKLOG_CACHE_KEY] = (dictCaches = new Dictionary<string, List<TWorkNoteItem>>());
                if (!dictCaches.ContainsKey(month)) dictCaches[month] = new List<TWorkNoteItem>();
                else dictCaches[month].RemoveAll(n => n.NoteID == item.NoteID && string.IsNullOrWhiteSpace(n.NoteBody));

                if (!dictCaches[month].Exists(n => n.NoteID == item.NoteID)) dictCaches[month].Add(item);
                var dayNotes = dictCaches[month].FindAll(n => n.NoteDate == item.NoteDate);
                dayNotes.ForEach(n => n.DayLoad = dayNotes.Sum(nt => decimal.Parse(nt.WorkLoad)).ToString());
            }
            return allNotes;
        }

        public List<TWorkNoteItem> GetMonthNotes(string userId, string month)
        {
            string[,] arrNotes = new string[0, 0];
            string message = string.Empty;
            var success = false;
            if (month.Length == 7) success = noteContext.GetNoteListByYearMonth(userId, month, ref arrNotes, ref message);
            var allNotes = new List<TWorkNoteItem>();
            if (success && arrNotes != null)
            {
                int bound = arrNotes.GetUpperBound(0) - arrNotes.GetLowerBound(0) + 1;
                for (int i = 0; i < bound; i++)
                {
                    int index = 0;
                    var item = new TWorkNoteItem();
                    item.NoteDay = arrNotes[i, index++];
                    item.NoteID = arrNotes[i, index++];
                    item.NoteState = arrNotes[i, index++];
                    item.NoteTopic = arrNotes[i, index++];
                    item.NoteDate = arrNotes[i, index++];
                    item.WorkLoad = arrNotes[i, index++];
                    item.DayLoad = arrNotes[i, index++];
                    allNotes.Add(item);
                }
            }
            return allNotes;
        }

        public ActionResult Delete()
        {
            string sid = Request["id"];//Request["id"];
            string date = Request["date"];
            decimal note_id = 0;
            if (decimal.TryParse(sid, out note_id) && note_id > 0)
            {
                string message = string.Empty;
                if (!noteContext.DeleteNote(note_id.ToString(), ref message)) throw new Exception(message);
                var allNotes = CacheProviders.SessionCache[Keys.WORKLOG_CACHE_KEY] as Dictionary<string, List<TWorkNoteItem>>;
                if (allNotes.ContainsKey(date)) allNotes[date].RemoveAll(it => it.NoteID == sid);
            }
            return Json(true);
        }
        [HttpGet]
        public ActionResult ContactList()
        {
            ViewData["ContactList"] = this.GetContactList();
            return View();
        }

        private List<TEmployeeItem> GetContactList()
        {
            var contacts = new string[0, 0];
            string message = string.Empty;
            var success = noteContext.GetUserList("Administrator", string.Empty, string.Empty, "0", ref contacts, ref message);
            if (!success) throw new Exception(message);
            List<TEmployeeItem> list = new List<TEmployeeItem>();
            int bound = contacts.GetUpperBound(0) - contacts.GetLowerBound(0) + 1;
            for (int i = 0; i < bound; i++)
            {
                int index = 0;
                var item = new TEmployeeItem();
                item.UserID = contacts[i, index++];
                item.UserName = contacts[i, index++];
                item.ShortCode = this.BuildShortCode(item.UserName);
                item.DepID = contacts[i, index++];
                item.DepName = contacts[i, index++];
                item.GroupID = contacts[i, index++];
                item.GroupName = contacts[i, index++];
                if (contacts[i, index++] == "0") item.IsAdmin = true;
                item.RoleName = contacts[i, index++];
                item.PurviewName = contacts[i, index++];
                item.Email = contacts[i, index++];
                item.Gender = contacts[i, index++];
                item.Tel = contacts[i, index++];
                item.SubTel = contacts[i, index++];
                item.QQ = contacts[i, index++];
                item.MSN = contacts[i, index++];
                index++;
                item.Leader = contacts[i, index++];
                list.Add(item);
            }
            return list;
        }
        private string BuildShortCode(string content)
        {
            if (string.IsNullOrWhiteSpace(content)) return string.Empty;
            var shortCode = string.Empty;
            var all = CacheProviders.GlobalCache[Keys.DICT_SHORTCODE] as List<Tuple<string, string, string>>;
            var miss = new Tuple<string, string, string>(string.Empty, "*", "*");
            for (var i = 0; i < content.Length; i++) shortCode += (all.FirstOrDefault(it => it.Item1 == (content[i] + string.Empty)) ?? miss).Item2;
            return shortCode;
        }
    }
}
